# -*- coding: utf-8 -*-
"""
StarRocks表数据增长统计 Provider。
"""
from __future__ import annotations

import json
from datetime import datetime, timedelta
from typing import Any, Dict, List, Optional, Tuple

from app.blueprints.reports.providers.base import BaseProvider, SafeDict
from app.services.report_service import ReportTemplateService
from app.utils.logger import FlinkLogger

logger = None


def get_logger():
    global logger
    if logger is None:
        logger = FlinkLogger.get_logger(__name__)
    return logger


class TableGrowthProvider(BaseProvider):
    """StarRocks表数据增长统计数据提供者"""

    def _get_sql_template(self) -> str:
        """从数据库 default_params 读取 SQL 模板"""
        if not self.template_code:
            raise ValueError("模板编码不能为空")
        
        try:
            tpl = ReportTemplateService.get_template_by_code(self.template_code)
            if not tpl:
                raise ValueError(f"模板 {self.template_code} 不存在")
            
            default_params = tpl.get("default_params")
            if isinstance(default_params, str):
                default_params = json.loads(default_params)
            
            sql_template = default_params.get("sql_template", "")
            if not sql_template:
                raise ValueError("模板配置中缺少 sql_template")
            
            return sql_template
        except Exception as e:
            get_logger().error(f"读取 SQL 模板失败: {e}", exc_info=True)
            raise

    def _get_field_labels(self) -> Dict[str, str]:
        """从数据库读取字段标签"""
        default_labels = {
            "database": "数据库名",
            "table": "表名",
            "current_rows": "当前行数",
            "current_size": "当前数据大小(字节)",
            "row_increment": "行数增量",
            "size_increment": "数据大小增量(字节)",
            "growth_status": "增长状态",
            "last_stat_time": "最后统计时间"
        }
        
        if self.template_code:
            try:
                tpl = ReportTemplateService.get_template_by_code(self.template_code)
                if tpl:
                    default_params = tpl.get("default_params")
                    if isinstance(default_params, str):
                        default_params = json.loads(default_params)
                    template_labels = default_params.get("field_labels", {})
                    if template_labels:
                        default_labels.update(template_labels)
            except Exception:
                pass
        
        return default_labels

    def _build_config_filter(self, starrocks_cluster_config: Dict[str, Any]) -> str:
        """构建StarRocks集群过滤条件"""
        cluster_id = starrocks_cluster_config.get("cluster_id")
        if cluster_id:
            return f"WHERE t.config_id = {cluster_id}"
        return "WHERE 1=1"

    def _build_table_filter(self, table_selection: Dict[str, Any]) -> str:
        """构建表过滤条件"""
        selection_type = table_selection.get("selection_type", "specific_tables")
        
        if selection_type == "specific_tables":
            table_names = table_selection.get("table_names", [])
            if table_Names:
                tables_str = "', '".join(table_names)
                return f" AND t.table_name IN ('{tables_str}')"
        elif selection_type == "all_in_databases":
            database_names = table_selection.get("database_names", [])
            if database_names:
                dbs_str = "', '".join(database_names)
                return f" AND t.database_name IN ('{dbs_str}')"
        
        return ""

    def _build_time_filter(self, time_dimension: Dict[str, Any]) -> str:
        """构建时间过滤条件"""
        dimension_type = time_dimension.get("dimension_type", "last_day")
        
        now = datetime.now()
        if dimension_type == "last_hour":
            time_start = (now - timedelta(hours=1)).strftime("%Y-%m-%d %H:%M:%S")
        elif dimension_type == "last_day":
            time_start = (now - timedelta(days=1)).strftime("%Y-%m-%d %H:%M:%S")
        elif dimension_type == "last_week":
            time_start = (now - timedelta(weeks=1)).strftime("%Y-%m-%d %H:%M:%S")
        elif dimension_type == "last_month":
            time_start = (now - timedelta(days=30)).strftime("%Y-%m-%d %H:%M:%S")
        elif dimension_type == "custom":
            time_start = time_dimension.get("custom_start")
            if not time_start:
                return ""
        else:
            return ""
        
        return f" AND t.last_stat_time >= '{time_start}'"

    def _build_stat_filter(self, statistics_config: Dict[str, Any]) -> str:
        """构建统计类型过滤条件"""
        stat_type = statistics_config.get("stat_type", "full_report")
        
        if stat_type == "no_growth":
            return "WHERE growth_status IN ('无增长', '下降')"
        else:
            return ""

    def _build_sort_clause(self, statistics_config: Dict[str, Any]) -> str:
        """构建排序子句"""
        sort_by = statistics_config.get("sort_by", "row_increment")
        
        if sort_by == "row_increment":
            return "row_increment DESC"
        elif sort_by == "size_increment":
            return "size_increment DESC"
        else:
            return "database_name ASC, table_name ASC"

    def _build_limit_clause(self, statistics_config: Dict[str, Any]) -> str:
        """构建LIMIT子句"""
        stat_type = statistics_config.get("stat_type", "full_report")
        
        if stat_type == "top_n":
            top_n = statistics_config.get("top_n", 10)
            return f"LIMIT {top_n}"
        else:
            return ""

    def collect(self) -> Dict[str, Any]:
        """收集数据"""
        try:
            get_logger().info("[表增长统计] 开始收集数据")
            
            # 使用默认监控数据库（从配置或环境变量获取）
            # TODO: 从配置中获取flink_cluster_monitor数据库的ID
            data_source_id = 1  # 暂时硬编码，后续从配置获取
            
            # 构建过滤条件
            starrocks_cluster_config = self.params.get("starrocks_cluster_config", {})
            table_selection = self.params.get("table_selection", {})
            statistics_config = self.params.get("statistics_config", {})
            time_dimension = self.params.get("time_dimension", {})
            
            config_filter = self._build_config_filter(starrocks_cluster_config)
            table_filter = self._build_table_filter(table_selection)
            time_filter = self._build_time_filter(time_dimension)
            stat_filter = self._build_stat_filter(statistics_config)
            sort_clause = self._build_sort_clause(statistics_config)
            limit_clause = self._build_limit_clause(statistics_config)
            
            # 获取字段标签
            field_labels = self._get_field_labels()
            
            # 获取SQL模板
            sql_template = self._get_sql_template()
            
            # 构建上下文
            context = {
                "config_filter": config_filter,
                "table_filter": table_filter,
                "time_filter": time_filter,
                "stat_filter": stat_filter,
                "sort_clause": sort_clause,
                "limit_clause": limit_clause,
                "database_label": field_labels.get("database", "数据库名"),
                "table_label": field_labels.get("table", "表名"),
                "current_rows_label": field_labels.get("current_rows", "当前行数"),
                "current_size_label": field_labels.get("current_size", "当前数据大小(字节)"),
                "row_increment_label": field_labels.get("row_increment", "行数增量"),
                "size_increment_label": field_labels.get("size_increment", "数据大小增量(字节)"),
                "growth_status_label": field_labels.get("growth_status", "增长状态"),
                "last_stat_time_label": field_labels.get("last_stat_time", "最后统计时间")
            }
            
            # 渲染SQL
            final_sql = sql_template.format_map(SafeDict(context))
            
            get_logger().info(f"[表增长统计] 执行查询SQL")
            
            # 执行查询
            with self.get_data_source_connection(data_source_id) as conn:
                cursor = conn.cursor()
                cursor.execute(final_sql)
                columns = [desc[0] for desc in cursor.description]
                rows = cursor.fetchall()
                
                get_logger().info(f"[表增长统计] 查询完成，返回 {len(rows)} 条记录")
                
                rows_list = [list(row) for row in rows]
            
            # 根据 display_fields 过滤
            filtered_columns, filtered_rows = self._filter_display_fields(columns, rows_list)
            if filtered_columns is not None:
                columns = filtered_columns
                rows_list = filtered_rows
            
            return {
                "query_result": {
                    "columns": columns,
                    "rows": rows_list
                }
            }
            
        except Exception as exc:
            get_logger().error(f"[表增长统计] 收集数据失败: {exc}", exc_info=True)
            raise

    def _filter_display_fields(
        self, columns: List[str], rows: List[List[Any]]
    ) -> Tuple[Optional[List[str]], Optional[List[List[Any]]]]:
        """根据 display_fields 过滤列"""
        display_fields = self.params.get("display_fields")
        if not display_fields:
            return None, None
        
        field_labels = self._get_field_labels()
        column_index_map = {col: idx for idx, col in enumerate(columns)}
        
        filtered_columns = []
        selected_indexes = []
        
        for field in display_fields:
            label = field_labels.get(field)
            if not label:
                continue
            column_idx = column_index_map.get(label)
            if column_idx is None:
                continue
            filtered_columns.append(label)
            selected_indexes.append(column_idx)
        
        if not filtered_columns:
            return [], []
        
        filtered_rows = [
            [row[idx] if idx < len(row) else None for idx in selected_indexes]
            for row in rows
        ]
        
        return filtered_columns, filtered_rows

    def validate_params(self) -> List[str]:
        """验证参数"""
        errors = []
        
        starrocks_cluster_config = self.params.get("starrocks_cluster_config")
        if not starrocks_cluster_config:
            errors.append("缺少StarRocks集群配置")
        elif not starrocks_cluster_config.get("cluster_id"):
            errors.append("StarRocks集群ID不能为空")
        
        statistics_config = self.params.get("statistics_config")
        if not statistics_config:
            errors.append("缺少统计配置")
        
        time_dimension = self.params.get("time_dimension")
        if not time_dimension:
            errors.append("缺少时间维度配置")
        
        return errors

    def preview_sql(self) -> str:
        """生成预览SQL"""
        try:
            starrocks_cluster_config = self.params.get("starrocks_cluster_config", {})
            table_selection = self.params.get("table_selection", {})
            statistics_config = self.params.get("statistics_config", {})
            time_dimension = self.params.get("time_dimension", {})
            
            config_filter = self._build_config_filter(starrocks_cluster_config)
            table_filter = self._build_table_filter(table_selection)
            time_filter = self._build_time_filter(time_dimension)
            stat_filter = self._build_stat_filter(statistics_config)
            sort_clause = self._build_sort_clause(statistics_config)
            limit_clause = self._build_limit_clause(statistics_config)
            
            field_labels = self._get_field_labels()
            sql_template = self._get_sql_template()
            
            context = {
                "config_filter": config_filter,
                "table_filter": table_filter,
                "time_filter": time_filter,
                "stat_filter": stat_filter,
                "sort_clause": sort_clause,
                "limit_clause": limit_clause,
                "database_label": field_labels.get("database", "数据库名"),
                "table_label": field_labels.get("table", "表名"),
                "current_rows_label": field_labels.get("current_rows", "当前行数"),
                "current_size_label": field_labels.get("current_size", "当前数据大小(字节)"),
                "row_increment_label": field_labels.get("row_increment", "行数增量"),
                "size_increment_label": field_labels.get("size_increment", "数据大小增量(字节)"),
                "growth_status_label": field_labels.get("growth_status", "增长状态"),
                "last_stat_time_label": field_labels.get("last_stat_time", "最后统计时间")
            }
            
            return sql_template.format_map(SafeDict(context))
        except Exception as exc:
            get_logger().error(f"生成预览SQL失败: {exc}", exc_info=True)
            raise
